package com.calvin.study.multithread.thread;

import java.util.concurrent.atomic.AtomicInteger;

import com.calvin.study.utils.Print;
import com.calvin.study.utils.ThreadUtil;


//通过实现Runnable接口的方式创建线程目标类更加适合多个线程的代码逻辑去共享计算和处理同一个资源的场景。 这个优点不是太好理解， 接下来通过具体例子说明一下。
public class Thread05 {

	public static final int MAX_AMOUNT = 5; // 商品数量

//	public static String getCurThreadName() {
//		return Thread.currentThread().getName();
//	}
//
//	public static void sleepMilliSeconds(int seconds) {
//		try {
//			Thread.sleep(seconds);
//		} catch (InterruptedException e) {
//			e.printStackTrace();
//		}
//	}

	//商店商品类（销售线程类） ， 一个商品一个销售线程， 每个线程异步销售4次
	static class StoreGoods extends Thread {

		StoreGoods(String name) {
			super(name);
		}

		private int goodsAmount = MAX_AMOUNT;
		

		public void run() {
			for (int i = 0; i <= MAX_AMOUNT; i++) {
				if (this.goodsAmount > 0) {
					Print.cfo(ThreadUtil.getCurThreadName() + " 卖出一件， 还剩： " + (--goodsAmount));
					ThreadUtil.sleepMilliSeconds(10);
				}
			}
			Print.cfo(ThreadUtil.getCurThreadName() + " 运行结束.");
		}
	}

	// 商场商品类型（target销售线程的目标类） ， 一个商品最多销售4次， 可以多人销售
	static class MallGoods implements Runnable {
		// 多人销售可能导致数据出错， 使用原子数据类型保障数据安全
		private AtomicInteger goodsAmount = new AtomicInteger(MAX_AMOUNT);

		public void run() {
			for (int i = 0; i <= MAX_AMOUNT; i++) {
				if (this.goodsAmount.get() > 0) {
					Print.cfo(ThreadUtil.getCurThreadName() + " 卖出一件， 还剩： " + (goodsAmount.decrementAndGet()));
					ThreadUtil.sleepMilliSeconds(10);
				}
			}
			Print.cfo(ThreadUtil.getCurThreadName() + " 运行结束.");
		}
	}

	public static void main(String args[]) throws InterruptedException {
		Print.hint("商店版本的销售");
		Thread thread = null;
		for (int i = 1; i <= 2; i++) {
			//创建了2个商店商品的销售线程
			thread = new StoreGoods("店员-" + i);
			thread.start();
		}
		Thread.sleep(1000);
		Print.hint("商场版本的销售");
		
//		执行时，创建了2个商店商品的销售线程，而销售数量在每个线程中独享（goodsAmount）每个线程各买各的，所以执行结果如下。
//		执行结果：
//		[main|Print.hint]：/--商店版本的销售--/
//		[Thread05$StoreGoods.run]：店员-1 卖出一件， 还剩： 4
//		[Thread05$StoreGoods.run]：店员-2 卖出一件， 还剩： 4
//		[Thread05$StoreGoods.run]：店员-2 卖出一件， 还剩： 3
//		[Thread05$StoreGoods.run]：店员-1 卖出一件， 还剩： 3
//		[Thread05$StoreGoods.run]：店员-1 卖出一件， 还剩： 2
//		[Thread05$StoreGoods.run]：店员-2 卖出一件， 还剩： 2
//		[Thread05$StoreGoods.run]：店员-2 卖出一件， 还剩： 1
//		[Thread05$StoreGoods.run]：店员-1 卖出一件， 还剩： 1
//		[Thread05$StoreGoods.run]：店员-2 卖出一件， 还剩： 0
//		[Thread05$StoreGoods.run]：店员-1 卖出一件， 还剩： 0
//		[Thread05$StoreGoods.run]：店员-2 运行结束.
//		[Thread05$StoreGoods.run]：店员-1 运行结束.
//		[main|Print.hint]：/--商场版本的销售--/

		//创建了一个共有的MallGoods对象（卖同一个商品）
		MallGoods mallGoods = new MallGoods();
		for (int i = 1; i <= 2; i++) {
			thread =  new Thread(mallGoods, "商场销售员-" + i);
			thread.start();
		}
		Print.cfo(ThreadUtil.getCurThreadName() + " 运行结束.");
		
//		执行结果：
//		[Thread05$MallGoods.run]：商场销售员-1 卖出一件， 还剩： 4
//		[Thread05$MallGoods.run]：商场销售员-2 卖出一件， 还剩： 3
//		[Thread05$MallGoods.run]：商场销售员-2 卖出一件， 还剩： 2
//		[Thread05$MallGoods.run]：商场销售员-1 卖出一件， 还剩： 1
//		[Thread05$MallGoods.run]：商场销售员-1 卖出一件， 还剩： 0
//		[Thread05$MallGoods.run]：商场销售员-2 运行结束.
//		[Thread05$MallGoods.run]：商场销售员-1 运行结束.
		
	}

}
